package com.mega.center.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.mega.center.system.mapper.I18nDataMapper;
import com.mega.center.system.mapper.I18nMapper;
import com.mega.center.system.model.dto.query.I18nQueryDTO;
import com.mega.center.system.model.entity.I18n;
import com.mega.center.system.model.entity.I18nData;
import com.mega.center.system.model.vo.I18nVO;
import com.mega.center.system.service.II18nService;
import com.mega.common.core.constant.CacheConstants;
import com.mega.common.core.enums.CommonMsgEnum;
import com.mega.common.core.exception.BusinessException;
import com.mega.common.core.web.service.MegaBaseServiceImpl;
import com.mega.common.redis.service.RedisService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 国际化 服务实现
 *
 * @author Eric
 * @version 1.0
 * @since 2020-09-28
 */
@Service
@Slf4j
public class I18nServiceImpl extends MegaBaseServiceImpl<I18nMapper, I18n> implements II18nService {

    @Autowired
    private I18nDataMapper i18nDataMapper;
    @Autowired
    private RedisService redisService;

    /**
     * 项目启动时，初始化参数到缓存
     */
    @PostConstruct
    public void init() {
        this.refresh();
        log.info("国际化数据初始化成功...");
    }

    /**
     * 当前服务名称
     */
    @Value("${spring.application.name}")
    private String serverName;

    /**
     * 新增国际化
     *
     * @param i18nVO 国际化实体类
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void create(I18nVO i18nVO) {
        I18n i18n = new I18n();
        BeanUtil.copyProperties(i18nVO, i18n);
        Integer codeCount = this.count(Wrappers.<I18n>lambdaQuery()
                .eq(I18n::getI18nCode, i18n.getI18nCode()));
        if (codeCount != null && codeCount > 0) {
            throw new BusinessException(CommonMsgEnum.CODE_REPEAT, i18n.getI18nCode());
        }
        //插入数据
        this.save(i18n);
        //新增详细数据
        if (CollectionUtil.isNotEmpty(i18nVO.getItems())) {
            List<I18nData> i18nDataList = i18nVO.getItems().stream().map(v -> {
                I18nData i18nData = new I18nData();
                BeanUtil.copyProperties(v, i18nData);
                i18nData.setI18nCode(i18n.getI18nCode());
                return i18nData;
            }).collect(Collectors.toList());
            i18nDataMapper.createBatch(i18nDataList);
        }
    }

    /**
     * 编辑国际化
     *
     * @param i18nVO 国际化实体类
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(I18nVO i18nVO) {
        I18n i18n = new I18n();
        BeanUtil.copyProperties(i18nVO, i18n);
        //判断数据是否为空
        I18n queryEntity = this.getById(i18n.getId());
        if (queryEntity == null) {
            throw new BusinessException(CommonMsgEnum.DATE_NOT_EXIST);
        }
        //查询修改后编码是否与原先一致
        if (!i18n.getI18nCode().equals(queryEntity.getI18nCode())) {
            //判断编码是否重复
            Integer codeCount = this.count(Wrappers.<I18n>lambdaQuery()
                    .eq(I18n::getI18nCode, i18n.getI18nCode()));
            if (codeCount != null && codeCount > 0) {
                throw new BusinessException(CommonMsgEnum.CODE_REPEAT, i18n.getI18nCode());
            }
        }
        //更新数据
        this.updateById(i18n);
        //更新或新增详细数据
        if (CollectionUtil.isNotEmpty(i18nVO.getItems())) {
            i18nVO.getItems().forEach(v -> {
                I18nData i18nData = new I18nData();
                BeanUtil.copyProperties(v, i18nData);
                i18nData.setI18nCode(i18n.getI18nCode());
                if (i18nData.getId() != null) {
                    i18nDataMapper.updateById(i18nData);
                } else {
                    i18nDataMapper.insert(i18nData);
                }
            });
        }
    }

    /**
     * 根据id删除国际化
     *
     * @param id 主键值
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void remove(Integer id) {
        I18n i18n = this.getById(id);
        if (i18n != null) {
            this.removeById(id);
        }
        i18nDataMapper.deleteByCode(i18n.getI18nCode());
    }

    /**
     * 分页查询
     *
     * @param page  分页
     * @param param 查询参数
     * @return
     */
    @Override
    public IPage<I18nVO> listOfPage(IPage<I18nVO> page, I18nQueryDTO param) {
        long total = this.baseMapper.count(param);
        if (total > 0) {
            page.setRecords(this.baseMapper.listOfPage(param));
        }
        page.setTotal(total);
        return page;
    }

    /**
     * 获取全部国际化数据
     *
     * @return
     */
    @Override
    public List<I18nVO> listAll() {
        String key = CacheConstants.I18N + serverName;
        if (redisService.hasKey(key)) {
            return redisService.getCacheList(key);
        } else {
            //查询所有国际化数据
            I18nQueryDTO param = new I18nQueryDTO();
            param.setSize(this.baseMapper.count(param));
            List<I18nVO> i18nVOList = this.baseMapper.listOfPage(param);
            //保存到缓存
            if (CollectionUtil.isNotEmpty(i18nVOList)) {
                redisService.setCacheList(key, i18nVOList);
            }
            return i18nVOList;
        }
    }

    /**
     * 刷新缓存
     */
    @Override
    public void refresh() {
        String key = CacheConstants.I18N + serverName;
        //清除缓存
        redisService.deleteObject(key);
        //查询所有国际化数据
        I18nQueryDTO param = new I18nQueryDTO();
        param.setSize(this.baseMapper.count(param));
        List<I18nVO> i18nVOList = this.baseMapper.listOfPage(param);
        //保存到缓存
        if (CollectionUtil.isNotEmpty(i18nVOList)) {
            redisService.setCacheList(key, i18nVOList);
        }
    }
}
